package com.yilin.tms.gps.controller;

import com.google.gson.reflect.TypeToken;
import com.yilin.commons.exception.BusinessException;
import com.yilin.commons.util.JsonUtil;
import com.yilin.commons.util.MapUtil;
import com.yilin.tms.core.application.ReturnData;
import com.yilin.tms.core.commons.base.BaseController;
import com.yilin.tms.core.commons.annotation.NotNull;
import com.yilin.tms.core.commons.annotation.UserTarget;
import com.yilin.tms.core.commons.utils.ParamUtil;
import com.yilin.tms.core.entity.gps.GpsPoint;
import com.yilin.tms.core.entity.gps.gaode.geo_track.GeoLocation;
import com.yilin.tms.core.entity.gps.gaode.geo_track.GeoPointTrack;
import com.yilin.tms.core.entity.order.transit.TransitOrder;
import com.yilin.tms.core.entity.user.UserType;
import com.yilin.tms.core.entity.user.account.Account;
import com.yilin.tms.core.entity.user.hatch.HatchGaodeMap;
import com.yilin.tms.core.entity.user.hatch.HatchPlatProduct;
import com.yilin.tms.gps.service.IGaodeWebService;
import com.yilin.tms.core.remote.IOrderRemote;
import com.yilin.tms.core.remote.IUserRemote;
import com.yilin.tms.gps.service.ITrailStorageService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.*;

/**
 * @author time
 */
@RestController
@RequestMapping("/gps/track/")
public class GpsTrackController extends BaseController {

    @Resource
    IOrderRemote orderRemote;
    @Resource
    IUserRemote userRemote;
    @Resource
    IGaodeWebService gaodeWebService;
    @Resource
    ITrailStorageService trailStorageService;

    /**
     * 司机向猎鹰添加轨迹点
     * 不使用猎鹰SDK,因为猎鹰SDK无法息屏运行
     */
    @PostMapping("addTrackPoints")
    @UserTarget(UserType.truckerUser)
    public ReturnData<Object> addTrackPoints(String traceId,String transportNo,String truckNo,String pointsJson) {
        //将轨迹点提交到 猎鹰终端
        if (getLoginUser().getGeoServiceId()==null)return jsonView(SUCCESS_CODE, "未初始化猎鹰！");
        if (getLoginUser().getGeoTerminalId()==null)return jsonView(SUCCESS_CODE, "未初始化终端！");
        List<GeoLocation> geoLocationList = JsonUtil.jsonToObject(pointsJson,new TypeToken<ArrayList<GeoLocation>>(){});
        List<GpsPoint> gpsPointList  = new ArrayList<>();
        for (GeoLocation geoLocation : geoLocationList) {
            GpsPoint gpsPoint = new GpsPoint();
            gpsPoint.setTraceId(traceId);
            gpsPoint.setTruckNo(truckNo);
            gpsPoint.setTransportNo(transportNo);
            gpsPoint.setGpsTime(new Date(geoLocation.getLocatetime()));
            gpsPoint.setBear(geoLocation.getDirection());
            gpsPoint.setSpeed(geoLocation.getSpeed());
            String[] split = geoLocation.getLocation().split(",");
            gpsPoint.setGdLntLat(new double[]{Double.parseDouble(split[0]), Double.parseDouble(split[1])});
            gpsPointList.add(gpsPoint);
        }
        trailStorageService.addTrackPoints(gpsPointList);
        gaodeWebService.addTracePoints(getLoginUser().getSuperiorPlatId(),getLoginUser().getGeoServiceId(),getLoginUser().getGeoTerminalId(),traceId,geoLocationList);
        return jsonView(SUCCESS_CODE, "轨迹上传成功！");
    }

    /**
     * 新增 初始化高德猎鹰轨迹服务
     * 自动创建服务
     */
    @PostMapping("generatePlatGeoServiceId")
    @UserTarget({UserType.zoneUser,UserType.platformUser})
    @NotNull({"platId","gdWebKey"})
    public ReturnData<String> generatePlatGeoServiceId(String platId,String gdWebKey) {
        ReturnData<HatchGaodeMap> gaodeMapHatch = userRemote.getGaodeMapHatch(platId);
        if (gaodeMapHatch.getData()!=null && gaodeMapHatch.getData().getGeoTrackSid()!=null  ){
            if (gaodeMapHatch.getData().getGdWebKey().equals(gdWebKey)) return jsonView(SUCCESS_CODE,"服务ID已生成",gaodeMapHatch.getData().getGeoTrackSid());
        }
        HatchPlatProduct platProduct = gaodeWebService.getHatchPlatProduct(platId);
        if (platProduct == null) return jsonErrView("请先保存产品生产配置");
        if (platProduct.getProductCode() == null) return jsonErrView("产品生产配置>产品码为空");
        String serviceId = gaodeWebService.addTrackService(gdWebKey, platProduct.getProductCode(), platProduct.getProductName());
        return jsonView(SUCCESS_CODE,"生成服务ID成功",serviceId);
    }

    /**
     * 新增 初始化高德猎鹰轨迹终端
     * 自动创建终端
     */
    @PostMapping("autoCreateTrackTerminal")
    public ReturnData<Map<String, String>> autoCreateTrackTerminal(String platId, String accountId) {
        Map<String, String> retMap = new HashMap<>();
        HatchGaodeMap hatchGaode = gaodeWebService.getHatchGaode(platId);
        Account account = ParamUtil.isSuccess(userRemote.getAccountById(accountId));
        if (account.getUserType() != UserType.truckerUser) throw new BusinessException("猎鹰创建轨迹失败，司机信息传入错误");
        if (hatchGaode.getGeoTrackSid() == null)  return jsonErrView("高德孵化参数轨迹服务ID未填写");
        retMap.put("geoServiceId", hatchGaode.getGeoTrackSid());
        if (hatchGaode.getGeoTrackSid().equals(account.getGeoServiceId()) && account.getGeoTerminalId() != null) {
            retMap.put("geoTerminalId", account.getGeoTerminalId());
            return jsonView(SUCCESS_CODE, "轨迹ID已存在且有效，返回已存在轨迹ID！", retMap);
        }
        String desc = (account.getName() == null ? "未认证" : account.getName()) + "_" + account.getPhone();
        String terminalId = gaodeWebService.addTrackTerminal(hatchGaode.getGdWebKey(), hatchGaode.getGeoTrackSid(), account.getId(), desc);
        retMap.put("geoTerminalId", terminalId);
        return jsonView(SUCCESS_CODE, "轨迹ID创建成功，请及时保存ID！", retMap);
    }

    /**
     * 创建轨迹
     */
    @PostMapping("createTraceId")
    public ReturnData<String> createTraceId(String platId, String geoServiceId, String geoTerminalId,String transportNo) {
        HatchGaodeMap hatchGaode = gaodeWebService.getHatchGaode(platId);
        String traceId = gaodeWebService.addTrackTrace(hatchGaode.getGdWebKey(), geoServiceId, geoTerminalId,transportNo);
        return jsonView(SUCCESS_CODE, "轨迹ID创建成功，请及时保存ID！", traceId);
    }

    /**
     * 查询司机位置
     */
    @PostMapping("getLastDriverPosition")
    public ReturnData<Object> getLastDriverPosition(String transportNo) {
        TransitOrder transitOrder = ParamUtil.isSuccess(orderRemote.getTransitOrderByNo(transportNo));
        Account account = ParamUtil.isSuccess(userRemote.getAccountById(transitOrder.getTransitTruckUserId()));
        if (transitOrder.getGeoTrackTraceId() == null) {
            GeoLocation geoLocation = new GeoLocation();
            geoLocation.setLocation(account.getDevicePosition());
            return jsonView(true, "获取成功", geoLocation);
        }
        HatchGaodeMap hatchGaode = gaodeWebService.getHatchGaode(transitOrder.getPlatId());
        GeoLocation geoLocation = gaodeWebService.queryTraceLastPoint(hatchGaode.getGdWebKey(), account.getGeoServiceId(), account.getGeoTerminalId(),transitOrder.getGeoTrackTraceId());
        if (geoLocation == null) {
            geoLocation = new GeoLocation();
            geoLocation.setLocation(account.getDevicePosition());
            return jsonView(true, "获取成功", geoLocation);
        }
        return jsonView(true, "获取成功", geoLocation);
    }

    /**
     * 实时查询司机位置
     */
    @PostMapping("getLastTerminalPosition")
    @ResponseBody
    public ReturnData<Object> getLastTerminalPosition(String platId, String geoServiceId, String geoTerminalId,String geoTrackTraceId) {
        HatchGaodeMap hatchGaode = gaodeWebService.getHatchGaode(platId);
        GeoLocation geoLocation = gaodeWebService.queryTraceLastPoint(hatchGaode.getGdWebKey(), geoServiceId, geoTerminalId,geoTrackTraceId);
        return jsonView(true, "获取成功", geoLocation);
    }

    /**
     * 查询运单轨迹 不推荐
     */
    @PostMapping("getTrackByTransportNo")
    public ReturnData<GeoPointTrack> getTrackByTransportNo(String transportNo, Integer page, Integer limit) {
        TransitOrder transitOrder = ParamUtil.isSuccess(orderRemote.getTransitOrderByNo(transportNo));
        Account account = ParamUtil.isSuccess(userRemote.getAccountById(transitOrder.getTransitTruckUserId()));
        HatchGaodeMap hatchGaode = gaodeWebService.getHatchGaode(transitOrder.getPlatId());
        GeoPointTrack track = gaodeWebService.queryTrackTrace(hatchGaode.getGdWebKey(),true, account.getGeoServiceId(), account.getGeoTerminalId(), transitOrder.getGeoTrackTraceId(), page, limit);
        return jsonView(true, "获取成功", track);
    }

    /**
     * 实时查询运单轨迹 推荐
     */
    @PostMapping("getTerminalTrack")
    public ReturnData<GeoPointTrack> getTerminalTrack(String platId, String geoServiceId, String geoTerminalId, String geoTrackTraceId, Integer page, Integer limit) {
        HatchGaodeMap hatchGaode = gaodeWebService.getHatchGaode(platId);
        GeoPointTrack track = gaodeWebService.queryTrackTrace(hatchGaode.getGdWebKey(),true,  geoServiceId, geoTerminalId, geoTrackTraceId, page, limit);
        return jsonView(true, "获取成功", track);
    }

    /**
     * 查询驾驶行为
     */
    @PostMapping("queryDrivingBehaviorByTransportNo")
    public ReturnData<Object> queryDrivingBehaviorByTransportNo(String transportNo) {
        TransitOrder transitOrder = ParamUtil.isSuccess(orderRemote.getTransitOrderByNo(transportNo));
        Account account = ParamUtil.isSuccess(userRemote.getAccountById(transitOrder.getTransitTruckUserId()));
        HatchGaodeMap hatchGaode = gaodeWebService.getHatchGaode(transitOrder.getPlatId());
        List<Map<String, Object>> drivingBehavior = gaodeWebService.queryDrivingBehavior(hatchGaode.getGdWebKey(), account.getGeoServiceId(), account.getGeoTerminalId(), transitOrder.getGeoTrackTraceId());
        List<Map<String, Object>> stayPoint = gaodeWebService.queryStayPoint(hatchGaode.getGdWebKey(), account.getGeoServiceId(), account.getGeoTerminalId(), transitOrder.getGeoTrackTraceId());
        return jsonView(true, "获取成功", MapUtil.generate(map -> {
            map.put("drivingBehavior",drivingBehavior);
            map.put("stayPoint",stayPoint);
        }));
    }

    /**
     * 实时查询驾驶行为 推荐
     */
    @PostMapping("queryDrivingBehavior")
    public ReturnData<Object> queryDrivingBehavior(String platId, String geoServiceId, String geoTerminalId, String geoTrackTraceId) {
        HatchGaodeMap hatchGaode = gaodeWebService.getHatchGaode(platId);
        List<Map<String, Object>> drivingBehavior = gaodeWebService.queryDrivingBehavior(hatchGaode.getGdWebKey(), geoServiceId, geoTerminalId, geoTrackTraceId);
        List<Map<String, Object>> stayPoint = gaodeWebService.queryStayPoint(hatchGaode.getGdWebKey(), geoServiceId, geoTerminalId, geoTrackTraceId);
        return jsonView(true, "获取成功", MapUtil.generate(map -> {
            map.put("drivingBehavior",drivingBehavior);
            map.put("stayPoint",stayPoint);
        }));
    }


    /**
     * 备份轨迹：未来一年内实现
     * 运单超过1年后被访问轨迹，因为猎鹰只保存1年，无法继续获取，
     * 此时可以将本地备份的轨迹上传到猎鹰终端，利用猎鹰重新分析轨迹
     * 一年之内必须备份轨迹，可以在运单结束时备份轨迹
     */
    public void saveTrackTrace() {

    }

    /**
     * 恢复轨迹：未来一年内实现
     * 运单超过1年后被访问轨迹，因为猎鹰只保存1年，无法继续获取，
     * 此时可以将本地备份的轨迹上传到猎鹰终端，利用猎鹰重新分析轨迹
     * 一年之内必须备份轨迹
     */
    public void resumeTrackTrace() {

    }
}
